﻿cms.DnD = function () {

    var _draggedElement;
    var _startX;
    var _startY;
    var _clone;
    var _root;
    var _dropzones = [];
    var _isDragging = false;
    var _isOnStartDragFired = false;
    var _onStartDrag;
    var _onEndDrag;
    var _dropzoneElement;
    var _dropzonePart = null;

    function _initDrag(parentTag, e) {
        e = e || window.event;
        var target = e.target || e.srcElement;
        while (target.parentNode.tagName != parentTag)
            target = target.parentNode;
        iLib.Dom.AddListener(document, "mouseup", _endDrag);
        iLib.Dom.AddListener(document, "mousemove", _drag);
        _startX = _getMouseX(e);
        _startY = _getMouseY(e);
        _draggedElement = target;
        _clone = null;
        _root = document.body;
        _isDragging = true;
        document.body.focus(); //Cancel out text selections
        document.onselectstart = function () { return false; }; // prevent text selection in IE
        target.ondragstart = function () { return false; }; //Prevent IE from dragging an image
        if (e && e.preventDefault) {
            e.preventDefault();
        }
        else {
            window.event.returnValue = false;
        }
        return false;
    }

    function _endDrag(e) {
        e = e || window.event;
        var x = _getMouseX(e);
        var y = _getMouseY(e);
        _findDropzone(x, y);
        iLib.Dom.RemoveListener(document, "mouseup", _endDrag);
        iLib.Dom.RemoveListener(document, "mousemove", _drag);
        if (_clone) {
            _clone.innerHTML = "";
            _root.removeChild(_clone);
            _clone = null;
        }
        _findDropzone(x, y);
        _root.style.cursor = "";
        if (_onEndDrag && _isDragging)
            _onEndDrag(_draggedElement, _dropzoneElement, _dropzonePart);
        _isDragging = false;
        _isOnStartDragFired = false;
    }

    function _drag(e) {
        e = e || window.event;
        // Fix for IE when an element is dragged and released outside the viewport
        if (!e.preventDefault && e.button == 0) {
            _endDrag(e);
            return false;
        }
        var x = _getMouseX(e);
        var y = _getMouseY(e);
        if (_clone == null && (Math.abs(x - _startX) > 2 || Math.abs(y - _startY) > 2)) {
            _clone = document.createElement("div");
            _clone.className = "draggedElement";
            _clone.style.position = "absolute";
            _clone.style.zIndex = 10000;
            _clone.innerHTML = _draggedElement.innerHTML;
            _root.appendChild(_clone);
            _root.style.cursor = "default";
            if (_onStartDrag)
                _onStartDrag(e);
            _isOnStartDragFired = true;
        }
        if (_clone != null) {
            _clone.style.top = y + "px";
            _clone.style.left = x + "px";
            _findDropzone(x, y);
        }
        //var target = e.target || e.srcElement;
        //document.body.focus(); //Cancel out text selections
        //document.onselectstart = function() { return false; }; // prevent text selection in IE
        //target.ondragstart = function() { return false; }; //Prevent IE from dragging an image
        return false;
    }

    function _findDropzone(x, y) {
        var found = false;
        var d;
        // Remove the "hover" status
        for (var i = 0; i < _dropzones.length; i++) {
            d = _dropzones[i];
            if (d.targetElement.className != "selected")
                d.targetElement.className = "";
            if (d.containerElement != null)
                d.containerElement.className = "";
        }
        // Find the element to hover
        for (var i = 0; i < _dropzones.length; i++) {
            d = _dropzones[i];
            if (x >= d.leftX && x <= d.rightX && y >= d.topY && y <= d.bottomY) {
                found = true;
                _dropzoneElement = d.targetElement;
                if (d.containerElement != null)
                    d.containerElement.className = "hover";
                if (d.targetElement.className != "selected") {
                    d.targetElement.className = "hover";
                    if (y <= d.topY + parseInt((d.bottomY - d.topY) / 2, 0)) {
                        d.targetElement.className += " upper";
                        _dropzonePart = "upper";
                    }
                    else {
                        d.targetElement.className += " lower";
                        _dropzonePart = "lower";
                    }
                }
                break;
            }
        }
        if (!found) {
            _dropzoneElement = null;
        }
    }

    function _dropzone(targetElement, containerElement) {
        this.targetElement = targetElement;
        this.containerElement = containerElement;
        this.leftX = iLib.Pos.FindX(targetElement);
        this.topY = iLib.Pos.FindY(targetElement);
        this.rightX = this.leftX + targetElement.offsetWidth;
        this.bottomY = this.topY + targetElement.offsetHeight;
    }

    function _addDropZone(targetElement, containerElement) {
        _dropzones[_dropzones.length] = new _dropzone(targetElement, containerElement);
    }

    function _clearDropZones() {
        _dropzones = [];
    }

    function _addStartDragHandler(handler) {
        _onStartDrag = handler;
    }

    function _addEndDragHandler(handler) {
        _onEndDrag = handler;
    }

    function _getIsDragging() {
        return _isDragging;
    }

    function _getDropZones() {
        return _dropzones;
    }

    function _getMouseX(e) {
        var x = 0;
        if (e.pageX) {
            x = e.pageX;
        }
        else if (e.clientX) {
            x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        }
        return parseInt(x);
    }

    function _getMouseY(e) {
        var y = 0;
        if (e.pageY) {
            y = e.pageY;
        }
        else if (e.clientY) {
            y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
        }
        return parseInt(y);
    }

    return {
        InitDrag: _initDrag,
        EndDrag: _endDrag,
        Drag: _drag,
        AddDropZone: _addDropZone,
        GetIsDragging: _getIsDragging,
        AddStartDragHandler: _addStartDragHandler,
        AddEndDragHandler: _addEndDragHandler,
        GetDropZones: _getDropZones,
        ClearDropZones: _clearDropZones
    }

} ();

